package org.deng.learn.concurrent.basic;

import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author 邓力宾
 * @date 2020/5/16 上午11:58
 * @desc ConcurrentLinkedQueue 介绍: https://tool.oschina.net/apidocs/apidoc?api=jdk-zh
 *  一个基于链接节点的无界线程安全队列。此队列按照 FIFO（先进先出）原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部，队列获取操作从队列头部获得元素。当多个线程共享访问一个公共 collection 时，ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许使用 null 元素。
 *
 * 此实现采用了有效的“无等待 (wait-free)”算法，该算法基于 Maged M. Michael 和 Michael L. Scott 合著的 Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms 中描述的算法。
 *
 * 需要小心的是，与大多数 collection 不同，size 方法不是 一个固定时间操作。由于这些队列的异步特性，确定当前元素的数量需要遍历这些元素。
 *
 * 此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
 *
 * 内存一致性效果：当存在其他并发 collection 时，将对象放入 ConcurrentLinkedQueue 之前的线程中的操作 happen-before 随后通过另一线程从 ConcurrentLinkedQueue 访问或移除该元素的操作。
 *
 * 构造方法摘要
 * ConcurrentLinkedQueue()
 *           创建一个最初为空的 ConcurrentLinkedQueue。
 * ConcurrentLinkedQueue(Collection<? extends E> c)
 *           创建一个最初包含给定 collection 元素的 ConcurrentLinkedQueue，按照此 collection 迭代器的遍历顺序来添加元素。
 * 方法摘要
 *  boolean	add(E e)
 *           将指定元素插入此队列的尾部。
 *  boolean	contains(Object o)
 *           如果此队列包含指定元素，则返回 true。
 *  boolean	isEmpty()
 *           如果此队列不包含任何元素，则返回 true。
 *  Iterator<E>	iterator()
 *           返回在此队列元素上以恰当顺序进行迭代的迭代器。
 *  boolean	offer(E e)
 *           将指定元素插入此队列的尾部。
 *  E	peek()
 *           获取但不移除此队列的头；如果此队列为空，则返回 null。
 *  E	poll()
 *           获取并移除此队列的头，如果此队列为空，则返回 null。
 *  boolean	remove(Object o)
 *           从队列中移除指定元素的单个实例（如果存在）。
 *  int	size()
 *           返回此队列中的元素数量。
 *  Object[]	toArray()
 *           返回以恰当顺序包含此队列所有元素的数组。
 * <T> T[]	toArray(T[] a)
 *           返回以恰当顺序包含此队列所有元素的数组；返回数组的运行时类型是指定数组的运行时类型。
 *
 *           插入取出元素源码分析：https://blog.51cto.com/14220760/2410661
 */

public class ConcurrentLinkedQueueDemo {

    public static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

    public static void test1(){
        for(int i = 0; i < 20; i++){
            final int j = i; //java内部类访问局部变量时局部变量必须声明为final, 实际上是传递了一份拷贝给内部类，
            new Thread(()->{
                if(j < 10){
                    queue.offer(j+"");
                }
            }).start();

        }
    }

    public static void showNode() throws NoSuchFieldException, IllegalAccessException {
        Field tailField = queue.getClass().getDeclaredField("tail");
        Field headField = queue.getClass().getDeclaredField("head");
        tailField.setAccessible(true);
        headField.setAccessible(true);
        Object tailNode = tailField.get(queue);
        Object headNode = headField.get(queue);

        Field itemField = tailNode.getClass().getDeclaredField("item");
        Field nextField = tailNode.getClass().getDeclaredField("next");
        itemField.setAccessible(true);
        nextField.setAccessible(true);

        Object headNoeItem = itemField.get(headNode);
        Object headNodeNext = nextField.get(headNode);

        Object tailNodeItem = itemField.get(tailNode);
        Object tailNodeNext = nextField.get(tailNode);


        System.out.println("headNode:"+headNode+"\n"+ "headNode-item:"+headNoeItem+"\nheadNode-next:"+headNodeNext+
                "\n\ntailNode:"+tailNode + "\ntailNode-item: "+tailNodeItem +"\ntailNode-next: " + tailNodeNext+
                "\n"+(tailNode == tailNodeNext));


        System.out.println("-----------------------------------------------------------------------------------");
    }
    public static void test2() throws NoSuchFieldException, IllegalAccessException {

        queue.offer("hello");
        showNode();
        queue.offer("world");
        showNode();



    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        test2();
    }
}
